#include "xAnimationControl.h"
#include "xKey.h"
#include "xMath.h"


namespace XE
{

	xAnimatinContral::xAnimatinContral()
	{

	}

	xAnimatinContral::~xAnimatinContral()
	{
		RemoveAllKey();
	}

	xKey* xAnimatinContral::GetKeyByIndex(UINT index) const 
	{
		if(index>m_KeyVector.size()-1)
			return NULL;
		return m_KeyVector[index];

	}

	HRESULT xAnimatinContral::RemoveKey(UINT index)
	{
		if(index>m_KeyVector.size()-1)
			return X_FAIL;
		m_KeyVector.erase(m_KeyVector.begin()+index);
		return X_OK;

	}

	HRESULT xAnimatinContral::SortKey()
	{
		return X_OK;

	}

	HRESULT xAnimatinContral::RemoveAllKey()
	{

		size_t size = m_KeyVector.size();
		for(size_t i = 0;i<size;++i)
		{
			SafeDelete(m_KeyVector.at(i));
		}
		m_KeyVector.clear();
		return X_OK;
	}


	xKey* xAnimatinContral::AddKey(float time)
	{
		xKey* pKey= ImplementCreateKey(time);
		size_t size =m_KeyVector.size();

		if(size==0)
		{
			m_KeyVector.push_back(pKey);
			return pKey;
		}

		if(time>m_KeyVector.at(size-1)->GetTime())
		{
			m_KeyVector.push_back(pKey);
			return pKey;
		}
	

		size_t lastKeyindex = 0;
		for(size_t i = 0;i<size;++i)
		{
			if(m_KeyVector.at(i)->GetTime()<time)
			{
				lastKeyindex = i;
			}else
			{
				break;
			}
		}
		m_KeyVector.insert(m_KeyVector.begin()+lastKeyindex+1,pKey);
		return pKey;
	}


	HRESULT xAnimatinContral::CalculateKey(float time ,xKey* pkey )
	{
		if(m_KeyVector.empty()||pkey==NULL)
			return X_FAIL;

		size_t size =m_KeyVector.size();
		if(time>=m_KeyVector[size-1]->GetTime())
		{
			pkey->Clone(m_KeyVector[size-1]);
			return X_OK;

		}

		//if(time<=m_KeyVector[0]->GetTime())
		//{
		//	pkey->Clone(m_KeyVector.at(0));
		//	return X_OK;
		//}
		--size;

		for(size_t i = 0;i<size;++i)
		{
			xKey* pKey1=m_KeyVector[i];
			xKey* pKey2 = m_KeyVector[i+1];
			float time1 = pKey1->GetTime();
			float time2 = pKey2->GetTime();
			if(time1<=time&&time2>=time)
			{
				float lenght =time2-time1;
				lenght = (time-time1)/lenght;
                     
				return  InterplateKey(pkey,pKey1,pKey2,lenght);

			}
		}

		return X_FAIL;

	}







    xString	xPositonAnimationContral::m_type = "xPositonAnimationContral";

	xKey* xPositonAnimationContral::ImplementCreateKey(float time) const 
	{
	       return new xPositionKey(time,xVector3(0,0,0));
	}

	HRESULT xPositonAnimationContral::\
		InterplateKey(xKey* ptargetKey, const xKey* pkey1,const xKey* pkey2,float time) const 
	{
		if(ptargetKey==NULL||pkey1==NULL||pkey2==NULL)
			return X_FAIL;

	 const	xPositionKey* pPoskey1= static_cast<const xPositionKey*>(pkey1);
	const   xPositionKey* pPoskey2= static_cast<const xPositionKey*>(pkey2);
	        xPositionKey* pTargetKey= static_cast< xPositionKey*>(ptargetKey);
	  	
		time=max(1.0f,time);
		time =min(0.0f,time);
		xVector3 tempos = pPoskey2->GetPosition()-pPoskey2->GetPosition();
		pTargetKey->SetPosition(pPoskey1->GetPosition()+tempos*time);
		return X_OK;
	}



	xString xRotationAnimationContral::m_type="xRotationAnimationContral";

	xKey*  xRotationAnimationContral::ImplementCreateKey(float time) const 
	{
           return new xRotationKey(time,xQuaternion(0.0f,0.0f,0.0f,1.0f));
	}



	HRESULT  xRotationAnimationContral::InterplateKey(\
		xKey* ptargetKey, const xKey* pkey1,const xKey* pkey2,float time) const
	{
		if(ptargetKey==NULL||pkey1==NULL||pkey2==NULL)
			return X_FAIL;


		time = max(1.0f,time);
		time =  min(0.0f,time);

		const xRotationKey* pRkey1= static_cast<const xRotationKey*>(pkey1);
		const xRotationKey* pRkey2= static_cast<const xRotationKey*>(pkey2);

		xRotationKey* pTarget= static_cast<xRotationKey*>(ptargetKey);

		xQuaternion quater;
		xMath::QuaternionSlerp(quater,pRkey1->GetRotation(),pRkey2->GetRotation(),time);
		pTarget->SetRotation(quater);

		return X_OK;

	}


}